package org.muninn.niagara.math;

import javax.baja.status.BStatusBoolean;
import javax.baja.status.BStatusNumeric;
import javax.baja.sys.BBoolean;
import javax.baja.sys.BComponent;
import javax.baja.sys.BIcon;
import javax.baja.sys.BInteger;
import javax.baja.sys.Context;
import javax.baja.sys.Flags;
import javax.baja.sys.Property;
import javax.baja.sys.Sys;
import javax.baja.sys.Type;

public class BNumericEncode extends BComponent
{
  /** Input to be encoded if a match is found **/
  public static final Property in = newProperty(Flags.SUMMARY, new BStatusNumeric());
  public void setIn(BStatusNumeric v) { set(in, v); }
  public BStatusNumeric getIn() { return (BStatusNumeric) get(in); }

  /** Pipe <code>in</code> to <code>out</code> regardless of matches **/
  public static final Property disable = newProperty(Flags.SUMMARY, false);
  public void setDisable(boolean v) { setBoolean(disable, v); }
  public boolean getDisable() { return getBoolean(disable); }

  /** Number of states against which to test <code>in</code> **/
  public static final Property total = newProperty(Flags.SUMMARY, 5);
  public void setTotal(int v) { setInt(total, v, null); }
  public int getTotal() { return getInt(total); }

  /** Encoded value of <code>in</code> **/
  public static final Property out = newProperty(Flags.SUMMARY|Flags.READONLY, new BStatusNumeric());
  public void setOut(BStatusNumeric v) { set(out, v); }
  public BStatusNumeric getOut() { return (BStatusNumeric) get(out); }

  /** Indicates whether or not a match has been found, always true if <code>disable</code> is true **/
  public static final Property match = newProperty(Flags.SUMMARY|Flags.READONLY, new BStatusBoolean());
  public void setMatch(BStatusBoolean v) { set(match, v); }
  public BStatusBoolean getMatch() { return (BStatusBoolean) get(match); }

  private static int tot;
  private static int input;

  public void started() { reset(); }

  public void changed(Property p, Context cx)
  {
    if (!isRunning())
      return;

    if (p.equals(total))
      reset();

    else if (!p.equals(match) && !p.equals(out))
    {
      if (getDisable())
        disable();
      
      else
        encode();
    }
  }

  public void reset()
  {
    tot = getTotal();
    this.removeAll();

    for (int i = 0; i < tot; i++)
      this.add("in" + (i+1), BInteger.make(0), Flags.SUMMARY);
    for (int i = 0; i < tot; i++)
      this.add("out" + (i+1), BInteger.make(0), Flags.SUMMARY);

    input = (int) getIn().getValue();
    for (int i = 0; i < tot; i++)
    {
      int temp = ((BInteger) get("in" + (i+1))).getInt();
      if (input == temp)
      {
        setMatch((BStatusBoolean) BStatusBoolean.make(BBoolean.make(true)));
        setOut((BStatusNumeric) BStatusNumeric.make(get("out" + (i+1))));
        return;
      }
      
      else
      {
        setOut(new BStatusNumeric(getIn().getValue()));
        setMatch((BStatusBoolean) BStatusBoolean.make(BBoolean.make(false)));
      }
    }
  }

  public void encode()
  {
    tot = getTotal();
    input = (int) getIn().getValue();
    for (int i = 0; i < tot; i++)
    {
      int temp = ((BInteger) get("in" + (i+1))).getInt();
      if (input == temp)
      {
        setMatch((BStatusBoolean) BStatusBoolean.make(BBoolean.make(true)));
        setOut((BStatusNumeric) BStatusNumeric.make(get("out" + (i+1))));
        return;
      }
      
      else
      {
        setOut(new BStatusNumeric(getIn().getValue()));
        setMatch((BStatusBoolean) BStatusBoolean.make(BBoolean.make(false)));
      }
    }
  }

  public void disable()
  {
    setOut(new BStatusNumeric(getIn().getValue()));
    setMatch((BStatusBoolean) BStatusBoolean.make(BBoolean.make(true)));
  }

  public BIcon getIcon() { return icon; }
  private static final BIcon icon = BIcon.make("local:|module://muninn/org/muninn/niagara/graphics/MuninnGroup.PNG");

  public static final Type TYPE = Sys.loadType(BNumericEncode.class);
  public Type getType() { return TYPE; }
} 
